#include <gtest/gtest.h>
#include <regex>
#include "scripting/script_lexer.h"
#include "test_print_info.h"

TEST(test_script_scan_is_identifier, test_script_scan)
{
    std::string str = "check_battery";

    std::regex reg("\\w+");
    printf("res: %d\n", std::regex_match(str, reg));
}

TEST(test_script_scan_scan_var, test_script_scan)
{
    const char *code = R"(var get_pose = GetPose("get_pose") #定义task)";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        printTokens(tokens.value());
        SUCCEED();
    }
    else
    {
        printErrorInfo(script_lexer);
        FAIL();
    }
}

TEST(test_script_scan_scan_var_err, test_script_scan)
{
    const char *code = R"(var get_pose("get_pose*") #定义错误的task)";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        printTokens(tokens.value());
        FAIL();
    }
    else
    {
        printErrorInfo(script_lexer);
        SUCCEED();
    }
}

TEST(test_script_scan_scan_run, test_script_scan)
{
    const char *code = R"(get_pose#执行task)";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        printTokens(tokens.value());
        SUCCEED();
    }
    else
    {
        printErrorInfo(script_lexer);
        FAIL();
    }
}
TEST(test_script_scan_scan_run_no_annotation, test_script_scan)
{
    const char *code = R"(get_pose)";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        printTokens(tokens.value());
        SUCCEED();
    }
    else
    {
        printErrorInfo(script_lexer);
        FAIL();
    }
}
TEST(test_script_scan_scan_if, test_script_scan)
{
    const char *code = R"(if(check_battery and !get_pose))";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        printTokens(tokens.value());
        SUCCEED();
    }
    else
    {
        printErrorInfo(script_lexer);
        FAIL();
    }
}
TEST(test_script_scan_scan_if_2, test_script_scan)
{
    const char *code = R"(
        if(check_battery and !get_pose)
            if(!arrive)
                navigation
        else
            recharge
    )";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        printTokens(tokens.value());
        SUCCEED();
    }
    else
    {
        printErrorInfo(script_lexer);
        FAIL();
    }
}

TEST(test_script_scan_scan_repeat, test_script_scan)
{
    const char *code = R"(
        #repeat
        repeat(3)
            navigation
    )";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        printTokens(tokens.value());
        SUCCEED();
    }
    else
    {
        printErrorInfo(script_lexer);
        FAIL();
    }
}

TEST(test_script_scan_scan_retry, test_script_scan)
{
    const char *code = R"(
        #retry
        retry(3)
            if(check_battery)
                navigation
            navigation
        end_retry
    )";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        printTokens(tokens.value());
        SUCCEED();
    }
    else
    {
        printErrorInfo(script_lexer);
        FAIL();
    }
}

TEST(test_script_scan_scan_while, test_script_scan)
{
    const char *code = R"(
        #while
        while(arrived)
            # sleep(1000)
            if(navigation)
                break
    )";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        printTokens(tokens.value());
        SUCCEED();
    }
    else
    {
        printErrorInfo(script_lexer);
        FAIL();
    }
}

TEST(test_script_scan_scan_reactive, test_script_scan)
{
    const char *code = R"(
        #reactive
        reactive(check_battery)
            navigation
    )";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        printTokens(tokens.value());
        SUCCEED();
    }
    else
    {
        printErrorInfo(script_lexer);
        FAIL();
    }
}

TEST(test_script_scan_scan_parallel, test_script_scan)
{
    const char *code = R"(
        #parallel
        parallel
        {
            navigation
            docking
            recharge
        }
    )";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        printTokens(tokens.value());
        SUCCEED();
    }
    else
    {
        printErrorInfo(script_lexer);
        FAIL();
    }
}


